using System.Collections.Generic;
using HtmlAgilityPack;
using NUnit.Framework;

namespace Fizzler.Tests
{
	[TestFixture]
	public class NthChild : SelectorBaseTest
	{
		/// <summary>
		/// Behaves the same as *:nth-child(2)
		/// </summary>
		[Test]
		public void No_Prefix_With_Digit()
		{
			var result = SelectList(":nth-child(2)");

			AssertForNoPrefixWithDigit(result);
		}
	
		[Test]
		public void Star_Prefix_With_Digit()
		{
			var result = SelectList("*:nth-child(2)");

			AssertForNoPrefixWithDigit(result);
		}

		[Test]
		public void Element_Prefix_With_Digit()
		{
			var result = SelectList("p:nth-child(2)");

			Assert.AreEqual(2, result.Count);
			Assert.AreEqual("p", result[0].Name);
			Assert.AreEqual("p", result[1].Name);
		}

		/// <summary>
		/// This is the same as No_Prefix_With_Digit or nth-child(2)
		/// </summary>
		/// <remarks>
		/// Means no repetition and starting from the second element.
		/// </remarks>
		[Test]
		public void Zero_N_Plus_2()
		{
			var result = SelectList(":nth-child(0n+2)");

			AssertForNoPrefixWithDigit(result);
		}

		/// <summary>
		/// Does not repeat and does not select so matches nothing
		/// </summary>
		[Test]
		public void Zero_N()
		{
			var result = SelectList(":nth-child(0n)");

			Assert.AreEqual(0, result.Count);
		}

		/// <summary>
		/// Matches nodes without skipping.
		/// </summary>
		/// <remarks>Matches every first node (as opposed to every second node, every third node, etc).</remarks>
		[Test]
		public void One_N()
		{
			var result = SelectList("li:nth-child(1n)");

			Assert.AreEqual(5, result.Count);
		}

		/// <summary>
		/// Matches nodes without skipping. Equivalent to 1n.
		/// </summary>
		[Test]
		public void One_N_Plus_Zero()
		{
			var result = SelectList("li:nth-child(1n+0)");

			Assert.AreEqual(5, result.Count);
		}

		/// <summary>
		/// Matches nodes without skipping.
		/// </summary>
		[Test]
		public void One_N_Plus_1()
		{
			var result = SelectList("li:nth-child(1n+1)");

			Assert.AreEqual(5, result.Count);
		}

		[Test]
		public void One_N_Plus_Two()
		{
			var result = SelectList("li:nth-child(1n+2)");

			Assert.AreEqual(4, result.Count);
			Assert.AreEqual("two", result[0].InnerText);
		}

		/// <summary>
		/// As One_N_Plus_Two but starts from two and goes *backwards* rather than forwards.
		/// </summary>
		[Test]
		public void Minus_One_N_Plus_Two()
		{
			var result = SelectList("li:nth-child(-1n+2)");

			Assert.AreEqual(2, result.Count);
			Assert.AreEqual("one", result[0].InnerText);
			Assert.AreEqual("two", result[1].InnerText);
		}

		[Test]
		public void Two_N()
		{
			var result = SelectList("li:nth-child(2n)");

			Assert.AreEqual(2, result.Count);
			Assert.AreEqual("two", result[0].InnerText);
			Assert.AreEqual("four", result[1].InnerText);
		}

		[Test]
		public void Three_N()
		{
			var result = SelectList("li:nth-child(3n)");

			Assert.AreEqual(1, result.Count);
			Assert.AreEqual("three", result[0].InnerText);
		}

		[Test]
		public void Three_N_Plus_One()
		{
			var result = SelectList("li:nth-child(3n+1)");

			Assert.AreEqual(2, result.Count);
			Assert.AreEqual("one", result[0].InnerText);
			Assert.AreEqual("four", result[1].InnerText);
		}

		private static void AssertForNoPrefixWithDigit(IList<HtmlNode> result)
		{
			Assert.AreEqual(5, result.Count);
			Assert.AreEqual("body", result[0].Name);
			Assert.AreEqual("p", result[1].Name);
			Assert.AreEqual("span", result[2].Name);
			Assert.AreEqual("p", result[3].Name);
			Assert.AreEqual("li", result[4].Name);
			Assert.AreEqual("two", result[4].InnerText);
		}
	}
	
	[TestFixture]
	public class NthLastChild : SelectorBaseTest {}

	[TestFixture]
	public class NthOfType : SelectorBaseTest {}

	[TestFixture]
	public class NthLastOfType : SelectorBaseTest {}

	[TestFixture]
	public class FirstOfType : SelectorBaseTest {}

	[TestFixture]
	public class LastOfType : SelectorBaseTest {}

	[TestFixture]
	public class OnlyOfType : SelectorBaseTest {}

}